package cn.remex.db.utils;

import cn.remex.core.exception.FunctionException;
import cn.remex.core.exception.NestedException;
import cn.remex.db.utils.exception.ServiceCode;
import cn.remex.db.utils.reflect.*;

import java.lang.reflect.Method;
import java.util.*;
import java.util.function.Function;

import static cn.remex.db.utils.Judgment.nullOrBlank;
/**
 * Map处理工具类
 */

/**
 * @author liuhengyang
 *         date 2014-9-24 下午2:31:15
 * @version 版本号码
 */
public class MapHelper {



	public static <K, T> Map<K, T> toMap(Object... keyAndValue) {
		if (keyAndValue != null && keyAndValue.length > 0) {
			Map map;
			boolean firstIsMap = keyAndValue[0] instanceof Map;
			map = firstIsMap ? (Map) keyAndValue[0] : new HashMap();
			Assert.isTrue((keyAndValue.length - (firstIsMap ? 1 : 0)) % 2 == 0, ServiceCode.FAIL, "key-value必须成对出现");
			for (int i = 0, c = (keyAndValue.length - (firstIsMap ? 1 : 0)); i < c; i++, i++) {
				map.put(keyAndValue[i + (firstIsMap ? 1 : 0)], keyAndValue[i + (firstIsMap ? 1 : 0) + 1]);
			}
			return map;
		}
		return null;
	}


	//LHY 2016/12/31 晚整理的链式扁平化数据向Objec或Json对象或MapTree结构的数据的底层抽象方法；之前的_flat2Object 都可以通过此方法实现，暂时没有改造
	@SuppressWarnings({"rawtypes", "unchecked"})
	public static<T> void flat2MapTree(T root, String path, String contextPath, Object value
			, CommSetter<T, String, Object> setter // 赋值
			, CommGetter<T, String, Object> getter //取值
			, CommConstructor<T, String, Object> beanConstructor //产生对象
			, CommConstructor<T, String, List> arrayConstructor //产生数组

			, CommSetter<List, String, Object> arrayItemSetter // 赋值
			, CommGetter<List, String, Object> arrayItemGetter //取值
	){

		int ci = -1, li = -1, li_r = -1;
		ci = path.indexOf('.');
		if (ci > 0 && ((li = path.indexOf("[")) > ci || li == -1)) {//L1属性此时是个对象
			String fieldName = path.substring(0, ci);
			Object obj = getter.visit(root, fieldName);
			if (null == obj) {
				obj = beanConstructor.create(root, fieldName);
				setter.assign(root, fieldName, obj);
			}
			flat2MapTree((T) obj, path.substring(ci + 1), (nullOrBlank(contextPath)?"":contextPath+".")+path.substring(0, ci), value, setter, getter, beanConstructor, arrayConstructor, arrayItemSetter, arrayItemGetter);
		} else if (li > 0) {//L2属性此时是个数组
			String fieldName = path.substring(0, li);
			String arrayIndexStr = path.substring(li + 1, (li_r = path.indexOf("]")));
			int arrayIndex = nullOrBlank(arrayIndexStr) ? -1 : Integer.parseInt(arrayIndexStr); //LHY 2015-1-16 新增对没有下表[] 的支持

			List arr = (List) getter.visit(root, fieldName);
			if (null == arr) {
				arr = arrayConstructor.create(root, fieldName);
				setter.assign(root, fieldName, arr);
			}

			//右中括号后面只会出现三种情况，1)结束，2).引用，3)[新数组引用
			if (li == path.length()) {
				//nextPath结束
				arrayItemSetter.assign(arr, arrayIndexStr, value);
				return;
			}
			String l_nextFlag = path.substring(li_r + 1, li_r + 2); // . or [
			if (".".equals(l_nextFlag)) {
				Object arrItem = arrayItemGetter.visit(arr, (nullOrBlank(contextPath)?"":contextPath+".")+path.substring(0, (li_r = path.indexOf("]")+1)));
				if (null==arrItem && (arrayIndex > arr.size() || 0 == arr.size() || arrayIndex < 0)) {//没有值 //当中括号为[]时n<0
					for (int i = arr.size(); i <= arrayIndex; i++) {
						arr.add(null);
					}
					arrItem = beanConstructor.create(root, String.valueOf(arrayIndex));
					if (arrayIndex == -1)
						arr.add(arrItem);
					else
						arr.set(arrayIndex, arrItem); //当中括号为[]时直接添加
				}
				flat2MapTree((T)arrItem, path.substring(li_r + (arrayIndex > 0 ? 2 : 1)),(nullOrBlank(contextPath)?"":contextPath+".")+path.substring(0,li_r), value, setter, getter, beanConstructor, arrayConstructor, arrayItemSetter, arrayItemGetter);
			} else if ("[".equals(l_nextFlag)) { // 数组嵌套
				throw new FunctionException(ServiceCode.FAIL, "暂不支持数组嵌套！");
			} else {
				throw new FunctionException(ServiceCode.FAIL, "非法字符：" + path);
			}
		} else {//基本类型 需要case
			setter.assign(root, path, value);
		}
	}
}
